import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Request, Response, NextFunction } from 'express';
import { SecurityEventEmitter } from '../events/security-event.emitter';
import { SECURITY_EVENT_KEY } from '../decorators/security-event.decorator';
import { SecurityEventType, SecurityLevel } from '../entities/security-log.entity';

@Injectable()
export class SecurityEventMiddleware implements NestMiddleware {
  private readonly logger = new Logger(SecurityEventMiddleware.name);

  constructor(
    private readonly reflector: Reflector,
    private readonly securityEventEmitter: SecurityEventEmitter,
  ) {}

  use(req: Request, res: Response, next: NextFunction) {
    // 获取路由元数据
    const handler = req.route?.stack?.[0]?.handle;
    if (!handler) {
      return next();
    }

    // 检查是否有安全事件装饰器
    const securityEventMetadata = this.reflector.get(
      SECURITY_EVENT_KEY,
      handler,
    );

    if (securityEventMetadata) {
      // 在响应结束时记录安全事件
      res.on('finish', () => {
        this.handleSecurityEvent(req, res, securityEventMetadata);
      });
    }

    next();
  }

  /**
   * 处理安全事件
   */
  private async handleSecurityEvent(
    req: Request,
    res: Response,
    metadata: any,
  ) {
    try {
      const { eventType, securityLevel, eventTitle, eventDescription, autoLog } = metadata;

      if (!autoLog) {
        return;
      }

      // 根据事件类型发射相应的事件
      const payload = {
        eventTitle,
        eventDescription,
        userId: (req as any).user?.id,
        username: (req as any).user?.username,
        ipAddress: this.getClientIP(req),
        userAgent: req.headers['user-agent'],
        requestUrl: req.url,
        requestMethod: req.method,
        additionalInfo: {
          statusCode: res.statusCode,
          responseTime: Date.now() - (req as any).startTime,
        },
      };

      switch (eventType) {
        case SecurityEventType.AUTH_SUCCESS:
          this.securityEventEmitter.emitAuthSuccess(payload);
          break;
        case SecurityEventType.AUTH_FAILED:
          this.securityEventEmitter.emitAuthFailed(payload);
          break;
        case SecurityEventType.UNAUTHORIZED_ACCESS:
          this.securityEventEmitter.emitUnauthorizedAccess(payload);
          break;
        case SecurityEventType.PERMISSION_DENIED:
          this.securityEventEmitter.emitPermissionDenied(payload);
          break;
        case SecurityEventType.VALIDATION_ERROR:
          this.securityEventEmitter.emitValidationError(payload);
          break;
        case SecurityEventType.BUSINESS_ERROR:
          this.securityEventEmitter.emitBusinessError(payload);
          break;
        case SecurityEventType.SYSTEM_ERROR:
          this.securityEventEmitter.emitSystemError(payload);
          break;
        case SecurityEventType.SUSPICIOUS_ACTIVITY:
          this.securityEventEmitter.emitSuspiciousActivity(payload);
          break;
        case SecurityEventType.RATE_LIMIT_EXCEEDED:
          this.securityEventEmitter.emitRateLimitExceeded(payload);
          break;
        case SecurityEventType.SQL_INJECTION_ATTEMPT:
          this.securityEventEmitter.emitSqlInjectionAttempt(payload);
          break;
        case SecurityEventType.XSS_ATTEMPT:
          this.securityEventEmitter.emitXssAttempt(payload);
          break;
        default:
          // 自定义事件
          this.securityEventEmitter.emitCustomEvent({
            eventType,
            securityLevel,
            ...payload,
          });
      }

      this.logger.debug(`安全事件已记录: ${eventTitle}`);
    } catch (error) {
      this.logger.error(`记录安全事件失败: ${error.message}`, error.stack);
    }
  }

  /**
   * 获取客户端IP地址
   */
  private getClientIP(req: Request): string {
    return (
      (req.headers['x-forwarded-for'] as string) ||
      (req.headers['x-real-ip'] as string) ||
      req.connection?.remoteAddress ||
      req.socket?.remoteAddress ||
      (req as any).ip ||
      'unknown'
    );
  }
}
